import random

from django import forms
from django.core.validators import RegexValidator
from django_redis import get_redis_connection
from web import models
from django.core.exceptions import ValidationError
from utils import encrypt
from web.forms.bootstrap import BootStrapForm


class RegisterModelForm(BootStrapForm, forms.ModelForm):
    mobile_phone = forms.CharField(label='手机号', max_length=32,
                                   validators=[RegexValidator(r'^(1[3-9])\d{9}', '手机号格式错误'), ]
                                   )
    password = forms.CharField(label="密码", min_length=8, max_length=64, widget=forms.PasswordInput(),
                               error_messages={'min_length': '密码长度不能小于8个字符',
                                               'max_length': '密码长度不能大于64个字符'})
    confirm_password = forms.CharField(label="确认密码", widget=forms.PasswordInput())
    code = forms.CharField(label='验证码', required=False)

    class Meta:
        model = models.UserInfo
        fields = ['username', 'password', 'confirm_password', 'mobile_phone', 'code']

    def clean_username(self):
        username = self.cleaned_data['username']
        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError("用户名已存在")
        return username

    def clean_password(self):
        pwd = self.cleaned_data['password']
        return encrypt.md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get('password', '')
        if not pwd:
            return pwd
        confirm_password = encrypt.md5(self.cleaned_data['confirm_password'])
        if pwd != confirm_password:
            raise ValidationError("两次密码不一致")
        return confirm_password

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已注册')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']
        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not mobile_phone:
            return code
        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')
        redis_code = redis_code.decode('utf-8')
        if code.strip() != redis_code:
            raise ValidationError('验证码错误，请重新输入')
        return code


class SendSmsForm(forms.Form):
    mobile_phone = forms.CharField(label='手机号', max_length=32,
                                   validators=[RegexValidator(r'^(1[3-9])\d{9}', '手机号格式错误'), ]
                                   )

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        tpl = self.request.GET.get('tpl')
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        # template_id = settings.TENCENT_SMS_TEMPLATE.get(tpl)
        # if not template_id:
        #     raise ValidationError('短信模版错误')
        if tpl == 'login' and not exists:
            raise ValidationError('手机号不存在')
        elif tpl == 'register' and exists:
            raise ValidationError('手机号已存在')
        code = random.randrange(1000, 9999)
        print(code)
        # res = send_sms_single(mobile_phone, template_id, [code, ])
        # if res['result'] != 0:
        #     raise ValidationError(f"短信发送失败，{res['errmsg']}")
        conn = get_redis_connection()
        conn.set(mobile_phone, code, ex=60)
        return mobile_phone


class LoginSMSForm(BootStrapForm, forms.Form):
    mobile_phone = forms.CharField(label='手机号', max_length=32,
                                   validators=[RegexValidator(r'^(1[3-9])\d{9}', '手机号格式错误'), ]
                                   )
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        user = models.UserInfo.objects.filter(mobile_phone=mobile_phone).first()
        if not user:
            raise ValidationError('手机号不存在')
        return user

    def clean_code(self):
        code = self.cleaned_data['code']
        user = self.cleaned_data.get('mobile_phone')
        if not user:
            return code
        conn = get_redis_connection()
        redis_code = conn.get(user.mobile_phone)
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')
        redis_code = redis_code.decode('utf-8')
        if code.strip() != redis_code:
            raise ValidationError('验证码错误，请重新输入')
        return code


class LoginForm(BootStrapForm, forms.Form):
    username = forms.CharField(label='用户名或手机号')
    password = forms.CharField(label='密码', widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label='验证码')

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_code(self):
        code = self.cleaned_data['code']
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码已过期，请重新获取')
        if code.strip().upper() != session_code.upper():
            raise ValidationError('验证码输入错误')
        return code

    def clean_password(self):
        return encrypt.md5(self.cleaned_data['password'])
